package main

import (
	"fmt"
	"strings"
	"github.com/garyburd/redigo/redis"
)

var (
	//全局唯一的redis连接池(池子很大，使用指针避免其拷贝效应)
	//初始值为nil
	redisPool *redis.Pool
)

/*func WriteRedis(name string, score int) {
	conn := GetReidisConn()
	_, err := conn.Do("set", name, score)
	HandleError(err, `conn.Do("set", name, score)`)
}

func ReadRedis(name string) (score int, err error) {
	fmt.Println("ReadRedis")
	conn := GetReidisConn()
	reply, err := conn.Do("get", name)
	score, err = redis.Int(reply, err)
	return score, err
}*/

/*
执行Redis命令
cmd Redis命令，如:"get name"
resultType 指定查询结果的类型（string,int,strings）
*/
func DoRedisCommand(cmd string, resultType string) (result interface{}, err error) {
	fmt.Println("ReadRedis")

	//从全局Redis连接池中获取一个连接
	conn := GetReidisConn()

	//将命令炸碎为单词
	strs := strings.Split(cmd, " ")

	//创建空接口切片，准备作为conn.Do的第二个不定长参数使用
	args := make([]interface{}, 0)
	//将第一个以后的单词，全部丢入空接口切片
	for _, x := range strs[1:] {
		args = append(args, x)
	}
	//fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!! strs=",strs,"args=",args)

	/*
	炸开后的第一个单词，即为Redis命令名称
	将上面定义的空接口切片展开(args...)，即为conn.Do所需要的参数
	*/
	reply, err := conn.Do(strs[0], args...)

	/*根据调用者传入的具体类型，将结果进行类型转换*/
	switch resultType {
	case "string":
		result, err = redis.String(reply, err)
	case "strings":
		result, err = redis.Strings(reply, err)
	case "int":
		result, err = redis.Int(reply, err)
	default:
		result, err = redis.String(reply, err)
	}

	//返回【结果/错误对】
	return result, err
}

/*
从全局连接池中获取一个连接
第一次有人访问时创建连接池，后续持续复用该池中的连接
*/
func GetReidisConn() redis.Conn {
	/*
	如果连接池没有创建，就创建，创建后全局的redisPool就不为空了
	以后就不再创建了
	*/
	if redisPool == nil {

		redisPool = &redis.Pool{
			//最大活动连接
			MaxActive: 100,
			//最大闲置连接
			MaxIdle: 10,
			//闲置超时时间
			IdleTimeout: 10,

			//拨号方法
			Dial: func() (redis.Conn, error) {
				//拨号连接
				return redis.Dial("tcp", "localhost:6379")
			}}
	}

	//从连接池中随机取得一个连接返回之
	return redisPool.Get()
}

/*
关闭全局连接池
*/
func CloseRedis() {
	if redisPool != nil {
		redisPool.Close()
	}
}
